package com.morgan.basemodule.fragment

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.fragment.app.Fragment
import androidx.viewpager.widget.ViewPager

/**
 *description：Fragment的可见性封装 https://mp.weixin.qq.com/s/N14RPbgqa-m1tJUGz6_p3g
 *<br>author：caowugao
 *<br>time：2021/3/30 0030 17:26
 */
open class VisibilityFragment : Fragment(), OnVisibilityChangedListener, View.OnAttachStateChangeListener {

    private val TAG = VisibilityFragment::class.java.simpleName
    /**
     * 宿主Activity可见性
     */
    private var actVisible = false

    /**
     * 子Fragment的可见性监听，用于回调给子Fragment。
     */
    private val childFragVisibilityListener : ArrayList<OnVisibilityChangedListener> by lazy { ArrayList() }

    /**
     * 父Fragment，一个Fragment里面可能包含子Fragment
     */
    private var selfParentFragment : VisibilityFragment? = null


    /**
     * 综合 replace、show/hide 、viewpager、fragment嵌套场景后 得出最终的fragment可见性
     * */
    private var selfVisible = false

    fun addChildFragVisibilityListener(listener : OnVisibilityChangedListener) {
        if (!childFragVisibilityListener.contains(listener)) {
            childFragVisibilityListener.add(listener)
        }
    }

    fun removeChildFragVisibilityListener(listener : OnVisibilityChangedListener) {
        childFragVisibilityListener.remove(listener)
    }

    private fun getSimpleName() = this.javaClass.simpleName

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.e(TAG, "${getSimpleName()} onAttach: ")
        val pFragment = parentFragment
        if (pFragment != null && pFragment is VisibilityFragment) {
            selfParentFragment = pFragment
            selfParentFragment?.addChildFragVisibilityListener(this)
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.e(TAG, "${getSimpleName()} onViewCreated: ")
        //// 处理直接 replace 的 case
        view.addOnAttachStateChangeListener(this)
    }

    override fun onResume() {
        super.onResume()
        Log.e(TAG, "${getSimpleName()} onResume: ")
        onVisibilityByReplace(true)
    }

    override fun onPause() {
        super.onPause()
        Log.e(TAG, "${getSimpleName()} onPause: ")
        onVisibilityByReplace(false)
    }

    override fun onDestroyView() {
        view?.removeOnAttachStateChangeListener(this)
        super.onDestroyView()
        Log.e(TAG, "${getSimpleName()} onDestroyView: ")
    }

    override fun onDetach() {
        selfParentFragment?.removeChildFragVisibilityListener(this)
        super.onDetach()
        selfParentFragment = null
        Log.e(TAG, "${getSimpleName()} onDetach: ")
    }

    /**
     * replace操作处理
     */
    protected open fun onVisibilityByReplace(visible: Boolean) {
        if (actVisible.equals(visible)) {
            return
        }
        Log.e(TAG, "${getSimpleName()} onVisibilityByReplace: $visible")
        actVisible = visible
        if (userVisibleHint) {
            onVisibilityChanged(visible)
        }
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        val currentVisible = !hidden
        Log.e(TAG, "${getSimpleName()} onHiddenChanged:before: $currentVisible")
        onVisibilityByShowHide(currentVisible)
    }

    /**
     * ViewPager 嵌套 Fragment
     * 可能先于Fragment的生命周期被调用（在FragmentPagerAdapter中，在Fragment被add之前这个方法就被调用了），
     * 所以在这个方法中进行操作之前，可能需要先判断一下生命周期是否执行了。
     */
    override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        Log.e(TAG, "${getSimpleName()} setUserVisibleHint: isVisibleToUser:$isVisibleToUser")
        val parentFragVisible = if (selfParentFragment != null) selfParentFragment!!.isFragmentVisible() else actVisible
        val currentVisible = parentFragVisible && super.isVisible() && userVisibleHint
        Log.e(TAG, "${getSimpleName()} setUserVisibleHint: actVisible:$actVisible, parentFragVisible:$parentFragVisible, super.isVisible:${super.isVisible()}, userVisibleHint:$userVisibleHint, currentVisible:$currentVisible")
        onVisibilityChanged(currentVisible)
    }

    /**
     * show/hide操作处理
     */
    protected open fun onVisibilityByShowHide(visible: Boolean) {
        onVisibilityChanged(visible)
    }


    /**
    * 是否可见（Activity处于前台、Tab被选中、Fragment被添加、Fragment没有隐藏、Fragment.View已经Attach）
    */
    fun isFragmentVisible(): Boolean = selfVisible

    /**
     * fragment可见性改变
     */
    override fun onVisibilityChanged(visible: Boolean) {
        if (selfVisible.equals(visible)) {
            return
        }
        selfVisible = visible
        Log.e(TAG, "${getSimpleName()} onVisibilityChanged: visible:${visible}")
        childFragVisibilityListener.forEach {listener ->
            listener.onVisibilityChanged(visible)
        }

    }

    override fun onViewAttachedToWindow(v: View?) {
        Log.e(TAG, "${getSimpleName()} onViewAttachedToWindow:")
        onVisibilityChanged(true)
    }

    override fun onViewDetachedFromWindow(v: View?) {
        Log.e(TAG, "${getSimpleName()} onViewDetachedFromWindow:")
        onVisibilityChanged(false)
    }

}